﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace BdiSyndicatonWarmup
{
    public partial class WarmUp : Form
    {
        private DataTable dtRequest = new DataTable();
        private string folderName = "csvfile";
        private delegate void DispResponseDelegate(string machineName, IBdiHttpWebResponse bdiResponse);
        private Task t;
        CancellationTokenSource cts;

        public WarmUp()
        {
            InitializeComponent();

            Initialize();
        }
        
        private void cmbRequest_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = cmbRequest.SelectedIndex;

            if (index < dtRequest.Rows.Count)
            {
                txtHeaders.Text = dtRequest.Rows[index][1].ToString();
                txtBody.Text = dtRequest.Rows[index][2].ToString();
            }
        }

        private async void lstCsvFile_SelectedIndexChanged(object sender, EventArgs e)
        {
            cklUrlList.Items.Clear();
            for (int i = 0; i < lstCsvFile.Items.Count; i++)
            {
                if (lstCsvFile.GetSelected(i))
                {
                    ArrayList list = await BdiCsvRead.ReadMachineNameFromCsvFile(folderName + "\\" + lstCsvFile.Items[i].ToString());

                    foreach (string machineName in list)
                    {
                        cklUrlList.Items.Add("http://" + machineName + "/bdisyn/v2/");
                    }
                }
            }

        }

        private void btnAllSelect_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < cklUrlList.Items.Count; i++)
            {
                if (!cklUrlList.GetItemChecked(i))
                {
                    cklUrlList.SetItemChecked(i, true);
                }
            }
        }

        private void btnAllCancel_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < cklUrlList.Items.Count; i++)
            {
                if (cklUrlList.GetItemChecked(i))
                {
                    cklUrlList.SetItemChecked(i, false);
                }
            }
        }

        //private void txtTimes_TextChanged(object sender, EventArgs e)
        //{
        //    string strInput = this.txtTimes.Text.ToString();
        //    string strRegex = @"^\d+$";

        //    if (!Regex.IsMatch(strInput, strRegex))
        //    {
        //        txtTimes.SelectAll();
        //        MessageBox.Show("Please enter the number.");
        //        return;
        //    }
        //}
        
        private void btnExecute_Click(object sender, EventArgs e)
        {
            if(string.IsNullOrEmpty(txtHeaders.Text.Trim()))
            {
                MessageBox.Show("Please enter Request Headers.");
                txtHeaders.Focus();
                return;
            }

            if (string.IsNullOrEmpty(txtBody.Text.Trim()))
            {
                MessageBox.Show("Please enter Request Body.");
                txtBody.Focus();
                return;
            }

            bool isSelect = false;
            for (int i = 0; i < cklUrlList.Items.Count; i++)
            {
                if (cklUrlList.GetItemChecked(i))
                {
                    isSelect = true;
                    break;
                }
            }
            if (!isSelect)
            {
                MessageBox.Show("Please select send url.");
                cklUrlList.Focus();
                return;
            }

            ArrayList list = new ArrayList();
            //SendRequest();
            for (int i = 0; i < cklUrlList.Items.Count; i++)
            {
                if (!cklUrlList.GetItemChecked(i))
                {
                    continue;
                }
                string url = cklUrlList.Items[i].ToString();
                list.Add(url);
            }

            int count = (int)numTime.Value;

            cts = new CancellationTokenSource();  
            t = new Task(() => SendRequest(list, count, cts.Token), cts.Token);  
            t.Start();
        }

        private void txtHeaders_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Modifiers == Keys.Control && e.KeyCode == Keys.A)
            {
                ((TextBox)sender).SelectAll();
            }
        }

        private void txtBody_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Modifiers == Keys.Control && e.KeyCode == Keys.A)
            {
                ((TextBox)sender).SelectAll();
            }
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            lstResposeResult.Items.Clear();
        }

        private void WarmUp_SizeChanged(object sender, EventArgs e)
        {
            grbRequest.Width = (int)(WarmUp.ActiveForm.Width * 0.65);
            grbRequest.Height = WarmUp.ActiveForm.Height - 60;

            grbCsvFile.Width = (int)(grbRequest.Width * 0.31);
            grbCsvFile.Height = (int)(grbRequest.Height * 0.45);
            lstCsvFile.Width = grbCsvFile.Width - 13;
            lstCsvFile.Height = grbCsvFile.Height - 20;

            grbUrlList.Width = grbCsvFile.Width;
            grbUrlList.Height = (int)(grbRequest.Height * 0.51);
            grbUrlList.Top = grbCsvFile.Height + 20;
            cklUrlList.Width = grbUrlList.Width - 13;
            cklUrlList.Height = grbUrlList.Height - 45;

            lblRequestTemp.Left = grbCsvFile.Width + 16;
            cmbRequest.Left = lblRequestTemp.Left + 100;
            lblTimes.Left = lblRequestTemp.Left;
            numTime.Left = cmbRequest.Left;
            btnExecute.Left = numTime.Left + 86;

            grbRequestInfo.Width = (int)(grbRequest.Width * 0.665);
            grbRequestInfo.Height = grbRequest.Height - 80;
            grbRequestInfo.Left = grbCsvFile.Width + 16;
            txtHeaders.Width = grbRequestInfo.Width - 16;
            txtHeaders.Height = (int)(grbRequestInfo.Height * 0.37);
            lblRequestBody.Top = txtHeaders.Height + 36;
            txtBody.Top = lblRequestBody.Top + 16;
            txtBody.Width = txtHeaders.Width;
            txtBody.Height = (int)(grbRequestInfo.Height * 0.54);

            grbResponse.Left = grbRequest.Width + 12;
            grbResponse.Width = (int)(WarmUp.ActiveForm.Width * 0.32);
            grbResponse.Height = WarmUp.ActiveForm.Height - 60;
            lstResposeResult.Width = grbResponse.Width - 12;
            lstResposeResult.Height = grbResponse.Height - 48;
            btnClear.Top = lstResposeResult.Height + 20;
        }

        private void Initialize()
        {
            try
            {
                // Initialize csv file list 
                lstCsvFile.DataSource = BdiFileRead.GetCsvFileName(folderName);

                // Initialize Request Template 
                dtRequest = BdiXmlRead.ReadXmlData("RequestTemplate.xml");
                cmbRequest.DisplayMember = "name";
                cmbRequest.DataSource = dtRequest;
                cmbRequest.SelectedIndex = 0;

                // Initialize Transmission times
                numTime.Value = 10;

                // Initialize Respose Result list
                lstResposeResult.GridLines = true;
                lstResposeResult.FullRowSelect = true;
                lstResposeResult.View = View.Details;
                lstResposeResult.Scrollable = true;
                lstResposeResult.MultiSelect = false;
                lstResposeResult.HeaderStyle = ColumnHeaderStyle.Clickable;

                lstResposeResult.Columns.Add("#", 60, HorizontalAlignment.Center);
                lstResposeResult.Columns.Add("HttpStatusCode", 100, HorizontalAlignment.Center);
                lstResposeResult.Columns.Add("Host", 120, HorizontalAlignment.Center);
                lstResposeResult.Columns.Add("ResponseLatency", 100, HorizontalAlignment.Center);

                lstResposeResult.Visible = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private async void SendRequest(ArrayList list, int count, CancellationToken ct)
        {
            try
            {
                string requestBody = txtBody.Text.Trim();
                NameValueCollection headers = GetRequestHeaders();

                foreach (string strUrl in list)
                {
                    string machineName = string.Empty;

                    machineName = strUrl.Substring(strUrl.IndexOf("//") + 2, strUrl.Substring(strUrl.IndexOf("//") + 2).IndexOf("/"));

                    for (int j = 0; j < count; j++)
                    {
                        if (!ct.IsCancellationRequested)
                        {
                            using (IBdiHttpWebResponse bdiResponse = await BdiHttpWebRequest.CreatePostHttpResponse(strUrl, headers, requestBody))
                            {
                                DispResponseResult(machineName, bdiResponse);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private NameValueCollection GetRequestHeaders()
        {
            NameValueCollection requestHeaders = new NameValueCollection();
            string[] headers = txtHeaders.Lines.Select(x => x.Trim()).ToArray();
            foreach (string header in headers)
            {
                if (string.IsNullOrEmpty(header))
                {
                    continue;
                }
                string[] data = header.Split(':');
                if (data.Length < 2)
                {
                    continue;
                }
                requestHeaders.Add(data[0], data[1]);
            }
            return requestHeaders;
        }

        private void DispResponseResult(string machineName, IBdiHttpWebResponse bdiResponse)
        {
            //if (this.lstResposeResult.InvokeRequired == false)
            //{
                lstResposeResult.BeginUpdate();
                ListViewItem Item = new ListViewItem();
                Item.SubItems[0].Text = lstResposeResult.Items.Count.ToString();
                Item.SubItems.Add(bdiResponse.StatusCode);
                Item.SubItems.Add(machineName);
                Item.SubItems.Add(bdiResponse.RequestStreamLatency.ToString());

                lstResposeResult.Items.Add(Item);
                lstResposeResult.EndUpdate();
                lstResposeResult.Items[lstResposeResult.Items.Count - 1].EnsureVisible();
            //}
            //else
            //{
            //    DispResponseDelegate DMResponse = new DispResponseDelegate(DispResponseResult);

            //    this.lstResposeResult.Invoke(DMResponse, machineName, bdiResponse);

            //}
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            if (cts != null)
            {
                cts.Cancel();
            }
        }

        private void btnOne_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtHeaders.Text.Trim()))
            {
                MessageBox.Show("Please enter Request Headers.");
                txtHeaders.Focus();
                return;
            }

            if (string.IsNullOrEmpty(txtBody.Text.Trim()))
            {
                MessageBox.Show("Please enter Request Body.");
                txtBody.Focus();
                return;
            }

            bool isSelect = false;
            for (int i = 0; i < cklUrlList.Items.Count; i++)
            {
                if (cklUrlList.GetItemChecked(i))
                {
                    isSelect = true;
                    break;
                }
            }
            if (!isSelect)
            {
                MessageBox.Show("Please select send url.");
                cklUrlList.Focus();
                return;
            }

            ArrayList list = new ArrayList();
            //SendRequest();
            for (int i = 0; i < cklUrlList.Items.Count; i++)
            {
                if (!cklUrlList.GetItemChecked(i))
                {
                    continue;
                }
                string url = cklUrlList.Items[i].ToString();
                list.Add(url);
            }
            cts = new CancellationTokenSource();
            t = new Task(() => SendRequest(list, 1, cts.Token), cts.Token);
            t.Start();
        }
    }
}
